pub(crate) mod date_time_serde {
    use chrono::{DateTime, FixedOffset, Local, NaiveDateTime};
    use serde::{Serializer, Deserializer, Deserialize};

    const FORMAT: &str = "%Y-%m-%d %H:%M:%S%.3f";
    
    pub fn serialize<S>(
        date: &DateTime<Local>,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let s = format!("{}", date.format(FORMAT));
        serializer.serialize_str(&s)
    }
    
    pub fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<DateTime<Local>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        let dt = NaiveDateTime::parse_from_str(&s, FORMAT).map_err(serde::de::Error::custom)?;
        let tz = FixedOffset::east_opt(8 * 3600).unwrap();
        Ok(DateTime::from(dt.and_local_timezone(tz).unwrap()))
    }
}

pub(crate) mod date_time_serde_null {
    use chrono::{DateTime, FixedOffset, Local, NaiveDateTime};
    use serde::{Serializer, Deserializer, Deserialize};

    const FORMAT: &str = "%Y-%m-%d %H:%M:%S%.3f";

    pub fn serialize<S>(
        date: &Option<DateTime<Local>>,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if date.is_none() {
            return serializer.serialize_none();
        }
        let s = format!("{}", date.unwrap().format(FORMAT));
        serializer.serialize_str(&s)
    }

    pub fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Option<DateTime<Local>>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        if &s == "" {
            return Ok(None);
        }
        let dt = NaiveDateTime::parse_from_str(&s, FORMAT).map_err(serde::de::Error::custom)?;
        let tz = FixedOffset::east_opt(8 * 3600).unwrap();
        Ok(Some(DateTime::from(dt.and_local_timezone(tz).unwrap())))
    }
}

